bitkeeper revision 1.1159.1.53 (411ccd729CC_RzyLGa4nViY2XcSdig)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 13 Aug 2004 14:17:22 +0000 (14:17 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Fri, 13 Aug 2004 14:17:22 +0000 (14:17 +0000)
Separate controller backend from the controller factory, allowing
each controller to have its own backend domain.

tools/python/xen/xend/server/blkif.py
tools/python/xen/xend/server/controller.py
tools/python/xen/xend/server/netif.py

index cc49688ef59417c74a3b19afdc3660bc50c9e407..bea848bfcf59ec4ab424102cd0b929da15e30ca2 100755 (executable)
@@ -13,20 +13,109 @@ import channel
 import controller
 from messages import *
 
-class BlkifControllerFactory(controller.ControllerFactory):
-    """Factory for creating block device interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
+class BlkifBackendController(controller.BackendController):
+    """ Handler for the 'back-end' channel to a device driver domain.
     """
 
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
+    def __init__(self, factory, dom):
+        controller.BackendController.__init__(self, factory, dom)
         self.addMethod(CMSG_BLKIF_BE,
                        CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED,
                        self.recv_be_driver_status_changed)
         self.attached = 1
         self.registerChannel()
+        
+    def respond_be_create(self, msg, d):
+        """Response handler for a be_create message.
+        Calls I{d} with the block interface created.
+
+        @param msg: message
+        @type  msg: xu message
+        @param d: deferred to call
+        @type  d: Deferred
+        """
+        val = unpackMsg('blkif_be_create_t', msg)
+        blkif = self.factory.getInstanceByDom(val['domid'])
+        d.callback(blkif)
+
+    def respond_be_connect(self, msg):
+        """Response handler for a be_connect message.
+
+        @param msg: message
+        @type  msg: xu message
+        """
+        val = unpackMsg('blkif_be_connect_t', msg)
+        blkif = self.factory.getInstanceByDom(val['domid'])
+        if blkif:
+            blkif.send_fe_interface_status_changed()
+        else:
+            pass
+    
+    def respond_be_vbd_create(self, msg, dev, d):
+        """Response handler for a be_vbd_create message.
+        Tries to grow the vbd, and passes the deferred I{d} on for
+        the grow to call.
+
+        @param msg: message
+        @type  msg: xu message
+        @param dev: device
+        @type  dev: BlkDev
+        @param d: deferred to call
+        @type  d: Deferred
+        """
+        val = unpackMsg('blkif_be_vbd_create_t', msg)
+        blkif = self.factory.getInstanceByDom(val['domid'])
+        if blkif:
+            d1 = defer.Deferred()
+            d1.addCallback(self.respond_be_vbd_grow, dev, d)
+            if d: d1.addErrback(d.errback)
+            blkif.send_be_vbd_grow(val['vdevice'], response=d1)
+        else:
+            pass
+    
+    def respond_be_vbd_grow(self, msg, dev, d):
+        """Response handler for a be_vbd_grow message.
+
+        @param msg: message
+        @type  msg: xu message
+        @param dev: device
+        @type  dev: BlkDev
+        @param d: deferred to call
+        @type  d: Deferred or None
+        """
+        val = unpackMsg('blkif_be_vbd_grow_t', msg)
+       status = val['status']
+       if status != BLKIF_BE_STATUS_OKAY:
+            raise XendError("Adding extent to vbd failed: device %x, error %d"
+                            % (val['extent.device'], status))
+        if d:
+            d.callback(dev)
+
+    def recv_be_driver_status_changed(self, msg, req):
+        """Request handler for be_driver_status_changed messages.
+        
+        @param msg: message
+        @type  msg: xu message
+        @param req: request flag (true if the msg is a request)
+        @type  req: bool
+        """
+        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
+            for blkif in self.factory.getInstances():
+                if blkif.backendController == self:
+                    blkif.detach()
+
+class BlkifControllerFactory(controller.SplitControllerFactory):
+    """Factory for creating block device interface controllers.
+    """
 
-    def createInstance(self, dom, recreate=0):
+    def __init__(self):
+        controller.SplitControllerFactory.__init__(self)
+        self.attached = 1
+
+    def createInstance(self, dom, recreate=0, backend=0):
         """Create a block device controller for a domain.
 
         @param dom: domain
@@ -41,13 +130,13 @@ class BlkifControllerFactory(controller.ControllerFactory):
         if blkif:
             d.callback(blkif)
         else:
-            blkif = BlkifController(self, dom)
+            blkif = BlkifController(self, dom, backend)
             self.addInstance(blkif)
             if recreate:
                 d.callback(blkif)
             else:
                 d1 = defer.Deferred()
-                d1.addCallback(self.respond_be_create, d)
+                d1.addCallback(blkif.backendController.respond_be_create, d)
                 d1.addErrback(d.errback)
                 blkif.send_be_create(response=d1)
         return d
@@ -76,6 +165,9 @@ class BlkifControllerFactory(controller.ControllerFactory):
         blkif = self.getInstanceByDom(dom)
         return (blkif and blkif.getDevice(vdev)) or None
 
+    def createBackendController(self, dom):
+        return BlkifBackendController(self, dom)
+
     def setControlDomain(self, dom, recreate=0):
         """Set the back-end block device controller domain.
 
@@ -134,88 +226,7 @@ class BlkifControllerFactory(controller.ControllerFactory):
         for blkif in self.getInstances():
             blkif.reattached()
 
-    def respond_be_create(self, msg, d):
-        """Response handler for a be_create message.
-        Calls I{d} with the block interface created.
-
-        @param msg: message
-        @type  msg: xu message
-        @param d: deferred to call
-        @type  d: Deferred
-        """
-        val = unpackMsg('blkif_be_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        d.callback(blkif)
-    
-    def respond_be_connect(self, msg):
-        """Response handler for a be_connect message.
 
-        @param msg: message
-        @type  msg: xu message
-        """
-        val = unpackMsg('blkif_be_connect_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            blkif.send_fe_interface_status_changed()
-        else:
-            pass
-    
-    def respond_be_vbd_create(self, msg, dev, d):
-        """Response handler for a be_vbd_create message.
-        Tries to grow the vbd, and passes the deferred I{d} on for
-        the grow to call.
-
-        @param msg: message
-        @type  msg: xu message
-        @param dev: device
-        @type  dev: BlkDev
-        @param d: deferred to call
-        @type  d: Deferred
-        """
-        val = unpackMsg('blkif_be_vbd_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            d1 = defer.Deferred()
-            d1.addCallback(self.respond_be_vbd_grow, dev, d)
-            if d: d1.addErrback(d.errback)
-            blkif.send_be_vbd_grow(val['vdevice'], response=d1)
-        else:
-            pass
-    
-    def respond_be_vbd_grow(self, msg, dev, d):
-        """Response handler for a be_vbd_grow message.
-
-        @param msg: message
-        @type  msg: xu message
-        @param dev: device
-        @type  dev: BlkDev
-        @param d: deferred to call
-        @type  d: Deferred or None
-        """
-        val = unpackMsg('blkif_be_vbd_grow_t', msg)
-       status = val['status']
-       if status != BLKIF_BE_STATUS_OKAY:
-            raise XendError("Adding extent to vbd failed: device %x, error %d"
-                            % (val['extent.device'], status))
-        if self.attached:
-            if d:
-                d.callback(dev)
-        else:
-            self.reattachDevice(val['domid'], val['vdevice'])
-
-    def recv_be_driver_status_changed(self, msg, req):
-        """Request handler for be_driver_status_changed messages.
-        
-        @param msg: message
-        @type  msg: xu message
-        @param req: request flag (true if the msg is a request)
-        @type  req: bool
-        """
-        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
-            for blkif in self.getInstances():
-                blkif.detach()
 
 class BlkDev(controller.Dev):
     """Info record for a block device.
@@ -251,13 +262,13 @@ class BlkDev(controller.Dev):
         log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
         self.controller.send_be_vbd_destroy(self.vdev)
         
-class BlkifController(controller.Controller):
+class BlkifController(controller.SplitController):
     """Block device interface controller. Handles all block devices
     for a domain.
     """
     
-    def __init__(self, factory, dom):
-        controller.Controller.__init__(self, factory, dom)
+    def __init__(self, factory, dom, backend):
+        controller.SplitController.__init__(self, factory, dom, backend)
         self.devices = {}
         self.addMethod(CMSG_BLKIF_FE,
                        CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED,
@@ -322,7 +333,7 @@ class BlkifController(controller.Controller):
             d.callback(dev)
         else:
             d1 = defer.Deferred()
-            d1.addCallback(self.factory.respond_be_vbd_create, dev, d)
+            d1.addCallback(self.backendController.respond_be_vbd_create, dev, d)
             d1.addErrback(d.errback)
             self.send_be_vbd_create(vdev, response=d1)
         return d
@@ -346,7 +357,7 @@ class BlkifController(controller.Controller):
         for dev in self.devices.values():
             dev.attached = 0
             d1 = defer.Deferred()
-            d1.addCallback(self.factory.respond_be_vbd_create, None, None)
+            d1.addCallback(self.backendController.respond_be_vbd_create, None, None)
             self.send_be_vbd_create(vdev, response=d1)
 
     def reattachDevice(self, vdev):
@@ -389,8 +400,8 @@ class BlkifController(controller.Controller):
                         'evtchn'       : self.evtchn['port1'],
                         'shmem_frame'  : val['shmem_frame'] })
         d = defer.Deferred()
-        d.addCallback(self.factory.respond_be_connect)
-        self.factory.writeRequest(msg, response=d)
+        d.addCallback(self.backendController.respond_be_connect)
+        self.backendController.writeRequest(msg, response=d)
 
     def send_fe_interface_status_changed(self, response=None):
         msg = packMsg('blkif_fe_interface_status_changed_t',
@@ -403,21 +414,21 @@ class BlkifController(controller.Controller):
         msg = packMsg('blkif_be_create_t',
                       { 'domid'        : self.dom,
                         'blkif_handle' : 0 })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_disconnect(self, response=None):
         log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom)
         msg = packMsg('blkif_be_disconnect_t',
                       { 'domid'        : self.dom,
                         'blkif_handle' : 0 })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_destroy(self, response=None):
         log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom)
         msg = packMsg('blkif_be_destroy_t',
                       { 'domid'        : self.dom,
                         'blkif_handle' : 0 })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_vbd_create(self, vdev, response=None):
         dev = self.devices[vdev]
@@ -426,7 +437,7 @@ class BlkifController(controller.Controller):
                         'blkif_handle' : 0,
                         'vdevice'      : dev.vdev,
                         'readonly'     : dev.readonly() })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
         
     def send_be_vbd_grow(self, vdev, response=None):
         dev = self.devices[vdev]
@@ -437,7 +448,7 @@ class BlkifController(controller.Controller):
                         'extent.device'        : dev.device,
                         'extent.sector_start'  : dev.start_sector,
                         'extent.sector_length' : dev.nr_sectors })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_vbd_destroy(self, vdev, response=None):
         log.debug('>BlkifController>send_be_vbd_destroy> dom=%d vdev=%d', self.dom, vdev)
@@ -447,5 +458,5 @@ class BlkifController(controller.Controller):
                         'blkif_handle'         : 0,
                         'vdevice'              : dev.vdev })
         del self.devices[vdev]
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
     
index b3795aecedede6a141338799303ff7259d45ee93..cea9c38dfb05b0836b0efca13195395b1e11c030 100755 (executable)
@@ -270,7 +270,7 @@ class CtrlMsgRcvr:
         else:
             print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
             
-class ControllerFactory(CtrlMsgRcvr):
+class ControllerFactory:
     """Abstract class for factories creating controllers for a domain.
     Maintains a table of instances.
 
@@ -281,8 +281,8 @@ class ControllerFactory(CtrlMsgRcvr):
     """
 
     def __init__(self):
-        CtrlMsgRcvr.__init__(self)
         self.instances = {}
+        self.backends = {}
         self.dom = 0
         
     def addInstance(self, instance):
@@ -370,6 +370,111 @@ class Controller(CtrlMsgRcvr):
         self.deregisterChannel()
         self.factory.instanceClosed(self)
 
+class SplitControllerFactory(ControllerFactory):
+    """Factory for SplitControllers.
+    
+    @ivar backends:  mapping of domain id to backend
+    @type backends:  {int: BackendController}
+    """
+    
+    def __init__(self):
+        ControllerFactory.__init__(self)
+        self.backends = {}
+
+    def createInstance(self, dom, recreate=0, backend=0):
+        """Create an instance. Define in a subclass.
+
+        @param dom: domain
+        @type  dom: int
+        @param recreate: true if the instance is being recreated (after xend restart)
+        @type  recreate: int
+        @param backend: backend domain
+        @type  backend: int
+        @return: controller instance
+        @rtype:  SplitController (or subclass)
+        """
+        raise NotImplementedError()
+        
+    def getBackendController(self, dom):
+        """Get the backend controller for a domain.
+
+        @param dom: domain
+        @return: backend controller
+        """
+        ctrlr = self.backends.get(dom)
+        if ctrlr is None:
+            ctrlr = self.createBackendController(dom)
+            self.backends[dom] = ctrlr
+        return ctrlr
+
+    def createBackendController(self, dom):
+        """Create a backend controller. Define in a subclass.
+
+        @param dom: domain
+        """
+        raise NotImplementedError()
+
+    def delBackendController(self, ctrlr):
+        """Remove a backend controller.
+
+        @param ctrlr: backend controller
+        """
+        if ctrlr.dom in self.backends:
+            del self.backends[ctrlr.dom]
+
+    def backendControllerClosed(self, ctrlr):
+        """Callback called when a backend is closed.
+        """
+        self.delBackendController(ctrlr)
+
+class BackendController(CtrlMsgRcvr):
+    """Abstract class for a backend device controller attached to a domain.
+
+    @ivar factory: controller factory
+    @type factory: ControllerFactory
+    @ivar dom:     domain
+    @type dom:     int
+    @ivar channel: channel to the domain
+    @type channel: Channel
+    """
+
+    
+    def __init__(self, factory, dom):
+        CtrlMsgRcvr.__init__(self)
+        self.factory = factory
+        self.dom = int(dom)
+        self.channel = None
+        
+    def close(self):
+        self.lostChannel()
+
+    def lostChannel(self):
+        self.deregisterChannel()
+        self.factory.instanceClosed(self)
+
+
+class SplitController(Controller):
+    """Abstract class for a device controller attached to a domain.
+    A SplitController has a BackendContoller.
+    """
+
+    def __init__(self, factory, dom, backend):
+        Controller.__init__(self, factory, dom)
+        self.backendDomain = None
+        self.backendController = None
+        self.setBackendDomain(backend)
+        
+    def setBackendDomain(self, dom):
+        ctrlr = self.factory.getBackendController(dom)
+        self.backendDomain = ctrlr.dom
+        self.backendController = ctrlr
+
+    def getBackendDomain(self):
+        return self.backendDomain
+
+    def getBackendController(self):
+        return self.backendController
+
 class Dev:
     """Abstract class for a device attached to a device controller.
 
index 7a33ab8489e562fd3216cc5b3d37495cb78a1d59..f4247c670f620033159b7cf720f02025d09e6aee 100755 (executable)
@@ -18,20 +18,49 @@ import channel
 import controller
 from messages import *
 
-class NetifControllerFactory(controller.ControllerFactory):
-    """Factory for creating network interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
+class NetifBackendController(controller.BackendController):
+    """Handler for the 'back-end' channel to a device driver domain.
     """
-
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
+    
+    def __init__(self, factory, dom):
+        controller.BackendController.__init__(self, factory, dom)
         self.addMethod(CMSG_NETIF_BE,
                        CMSG_NETIF_BE_DRIVER_STATUS_CHANGED,
                        self.recv_be_driver_status_changed)
         self.attached = 1
         self.registerChannel()
 
-    def createInstance(self, dom, recreate=0):
+    def respond_be_connect(self, msg):
+        val = unpackMsg('netif_be_connect_t', msg)
+        dom = val['domid']
+        vif = val['netif_handle']
+        netif = self.factory.getInstanceByDom(dom)
+        if netif:
+            netif.send_interface_connected(vif)
+        else:
+            log.warning("respond_be_connect> unknown vif dom=%d vif=%d", dom, vif)
+            pass
+
+    def recv_be_driver_status_changed(self, msg, req):
+        val = unpackMsg('netif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
+            # If we are not attached the driver domain was changed, and
+            # this signals the new driver domain is ready.
+            for netif in self.factory.getInstances():
+                if netif.backendController == self:
+                    netif.reattach_devices()
+            self.attached = 1
+
+class NetifControllerFactory(controller.SplitControllerFactory):
+    """Factory for creating network interface controllers.
+    """
+
+    def __init__(self):
+        controller.ControllerFactory.__init__(self)
+        self.attached = 1
+
+    def createInstance(self, dom, recreate=0, backend=0):
         """Create or find the network interface controller for a domain.
 
         @param dom:      domain
@@ -40,7 +69,7 @@ class NetifControllerFactory(controller.ControllerFactory):
         """
         netif = self.getInstanceByDom(dom)
         if netif is None:
-            netif = NetifController(self, dom)
+            netif = NetifController(self, dom, backend=backend)
             self.addInstance(netif)
         return netif
 
@@ -63,6 +92,9 @@ class NetifControllerFactory(controller.ControllerFactory):
         netif = self.getInstanceByDom(dom)
         return (netif and netif.getDevice(vif)) or None
         
+    def createBackendController(self, dom):
+        return NetifBackendController(self, dom)
+
     def setControlDomain(self, dom, recreate=0):
         """Set the 'back-end' device driver domain.
 
@@ -83,27 +115,6 @@ class NetifControllerFactory(controller.ControllerFactory):
         """
         return self.dom
 
-    def respond_be_connect(self, msg):
-        val = unpackMsg('netif_be_connect_t', msg)
-        dom = val['domid']
-        vif = val['netif_handle']
-        netif = self.getInstanceByDom(dom)
-        if netif:
-            netif.send_interface_connected(vif)
-        else:
-            log.warning("respond_be_connect> unknown vif dom=%d vif=%d", dom, vif)
-            pass
-
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('netif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
-            # If we are not attached the driver domain was changed, and
-            # this signals the new driver domain is ready.
-            for netif in self.getInstances():
-                netif.reattach_devices()
-            self.attached = 1
-
 class NetDev(controller.Dev):
     """Info record for a network device.
     """
@@ -207,14 +218,13 @@ class NetDev(controller.Dev):
         self.controller.send_be_disconnect(self.vif, response=d)
         
 
-class NetifController(controller.Controller):
+class NetifController(controller.SplitController):
     """Network interface controller. Handles all network devices for a domain.
     """
     
-    def __init__(self, factory, dom):
-        controller.Controller.__init__(self, factory, dom)
+    def __init__(self, factory, dom, backend):
+        controller.SplitController.__init__(self, factory, dom, backend)
         self.devices = {}
-        
         self.addMethod(CMSG_NETIF_FE,
                        CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
                        self.recv_fe_driver_status_changed)
@@ -317,8 +327,8 @@ class NetifController(controller.Controller):
                         'tx_shmem_frame' : val['tx_shmem_frame'],
                         'rx_shmem_frame' : val['rx_shmem_frame'] })
         d = defer.Deferred()
-        d.addCallback(self.factory.respond_be_connect)
-        self.factory.writeRequest(msg, response=d)
+        d.addCallback(self.backendController.respond_be_connect)
+        self.backendController.writeRequest(msg, response=d)
 
     def send_interface_connected(self, vif, response=None):
         dev = self.devices[vif]
@@ -335,14 +345,14 @@ class NetifController(controller.Controller):
                       { 'domid'        : self.dom,
                         'netif_handle' : dev.vif,
                         'mac'          : dev.mac })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_disconnect(self, vif, response=None):
         dev = self.devices[vif]
         msg = packMsg('netif_be_disconnect_t',
                       { 'domid'        : self.dom,
                         'netif_handle' : dev.vif })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)
 
     def send_be_destroy(self, vif, response=None):
         dev = self.devices[vif]
@@ -350,4 +360,4 @@ class NetifController(controller.Controller):
         msg = packMsg('netif_be_destroy_t',
                       { 'domid'        : self.dom,
                         'netif_handle' : vif })
-        self.factory.writeRequest(msg, response=response)
+        self.backendController.writeRequest(msg, response=response)